<!DOCTYPE html>
<html>
<head>
	<!-- Global site tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id='UA-133422980-2"></script>
	<script>
	  window.dataLayer = window.dataLayer || [];
	  function gtag(){dataLayer.push(arguments);}
	  gtag('js', new Date());

	  gtag('config', 'UA-133422980-2');
	</script>

	<meta charset="utf-8">
	<meta http-equiv="x-ua-compatible" content="ie=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">

	<title>
		gem5: Adding parameters to SimObjects and more events 
	</title>

	<!-- SITE FAVICON -->
	<link rel="shortcut icon" type="image/gif" href="/assets/img/gem5ColorVert.gif"/>

	<link rel="canonical" href="http://localhost:4000/documentation/learning_gem5/part2/parameters/">
	<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700,800,600' rel='stylesheet' type='text/css'>
	<link href='https://fonts.googleapis.com/css?family=Muli:400,300' rel='stylesheet' type='text/css'>

	<!-- FAVICON -->
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

	<!-- BOOTSTRAP -->
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

	<!-- CUSTOM CSS -->
	<link rel="stylesheet" href="/css/main.css">
</head>


<body>
	<nav class="navbar navbar-expand-md navbar-light bg-light">
  <a class="navbar-brand" href="/">
		<img src="/assets/img/gem5ColorLong.gif" alt="gem5" height=55px>
	</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <!-- LIST FOR NAVBAR -->
    <ul class="navbar-nav ml-auto">
      <!-- HOME -->
      <li class="nav-item ">
        <a class="nav-link" href="/">Home</a>
      </li>

      <!-- ABOUT -->
			<li class="nav-item dropdown ">
				<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
					About
				</a>
				<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <a class="dropdown-item" href="/about">About gem5</a>
          <a class="dropdown-item" href="/publications">Publications</a>
          <a class="dropdown-item" href="/governance">Governance</a>
				</div>
			</li>

      <!-- DOCUMENTATION -->
			<li class="nav-item dropdown active">
				<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
					Documentation
				</a>
				<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
					<!-- Pull navigation from _data/documentation.yml -->
					
            <a class="dropdown-item" href="/documentation">gem5 documentation</a>
					
            <a class="dropdown-item" href="/documentation/learning_gem5/introduction">Learning gem5</a>
					
            <a class="dropdown-item" href="http://doxygen.gem5.org/release/current/index.html">gem5 Doxygen</a>
					
            <a class="dropdown-item" href="/documentation/reporting_problems">Reporting Problems</a>
					
				</div>
			</li>

      <!-- EVENTS -->
			<li class="nav-item dropdown ">
        <a class="nav-link" href="/events/">Events</a>
			</li>

      <!-- CONTRIBUTING -->
      <li class="nav-item ">
        <a class="nav-link" href="/contributing">Contributing</a>
      </li>

      <!-- BLOG -->
      <li class="nav-item ">
        <a class="nav-link" href="/blog">Blog</a>
      </li>

      <!-- SEARCH -->
			<li class="nav-item ">
        <a class="nav-link" href="/search">Search</a>
      </li>
    </ul>
  </div>
</nav>

	<main>
		<div class="sidenav-top">
  <div class="sidenav-brand bg-light">
    <a href="/"><img src="/assets/img/gem5ColorLong.gif" height="55px"></a>
  </div>
  <div class="search">
    <form action="/search" method="get">
      <!-- <label for="search-box"><i class="fa fa-search"></i></label> -->
      <input type="text" name="query">
      <button type="submit" name="submit"><i class="fa fa-search"></i></button>
    </form>
  </div>
</div>
<div class="sidenav">
  <!-- Pull navigation from _data/documentation.yml -->
  
    
  
    
    
      <a class="item" href="/documentation/learning_gem5/introduction" role="button" aria-expanded="false" aria-controls="collapseExample">
        Introduction
      </a>
      <div class="collapse " id="introduction">
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part1" role="button" aria-expanded="false" aria-controls="collapseExample">
        Getting Started
      </a>
      <div class="collapse " id="part1">
        
          <a class="subitem " href="/documentation/learning_gem5/part1/building">Building gem5</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/simple_config">Creating a simple configuration script</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/cache_config">Adding cache to configuration script</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/gem5_stats">Understanding gem5 statistics and output</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/example_configs">Using the default configuration scripts</a>
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part2" role="button" aria-expanded="false" aria-controls="collapseExample">
        Modifying/Extending
      </a>
      <div class="collapse show" id="part2">
        
          <a class="subitem " href="/documentation/learning_gem5/part2/environment">Setting up your development environment</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/helloobject">Creating a very simple SimObject</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/debugging">Debugging gem5</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/events">Event-driven programming</a>
        
          <a class="subitem active" href="/documentation/learning_gem5/part2/parameters">Adding parameters to SimObjects and more events</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/memoryobject">Creating SimObjects in the memory system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/simplecache">Creating a simple cache object</a>
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part3" role="button" aria-expanded="false" aria-controls="collapseExample">
        Modeling Cache Coherence with Ruby
      </a>
      <div class="collapse " id="part3">
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIintro">Introduction to Ruby</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-intro">MSI example cache protocol</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-declarations">Declaring a state machine</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-in-ports">In port code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-actions">Action code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-transitions">Transition code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/directory">MSI Directory implementation</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIbuilding">Compiling a SLICC protocol</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/configuration">Configuring a simple Ruby system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/running">Running the simple Ruby system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIdebugging">Debugging SLICC Protocols</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/simple-MI_example">Configuring for a standard protocol</a>
        
      </div>
    
      <a class="item" href="/documentation/learning_gem5/gem5_101/" role="button" aria-expanded="false" aria-controls="collapseExample">
        gem5 101
      </a>
      <div class="collapse " id="gem5_101">
        
      </div>
    
    
  
    
  
    
  
</div>


<div class="container" id="doc-container">
  <div class="edit"><a href="https://gem5.googlesource.com/public/gem5-website/+/refs/heads/master/README.md">Edit this page</a></div>
  <b>authors:</b> Jason Lowe-Power<br>
  

  <br>
  <h1 id="adding-parameters-to-simobjects-and-more-events">Adding parameters to SimObjects and more events</h1>

<p>One of the most powerful parts of gem5’s Python interface is the ability
to pass parameters from Python to the C++ objects in gem5. In this
chapter, we will explore some of the kinds of parameters for SimObjects
and how to use them building off of the simple <code class="highlighter-rouge">HelloObject</code> from the
previous chapters &lt;events-chapter&gt;.</p>

<h2 id="simple-parameters">Simple parameters</h2>

<p>First, we will add parameters for the latency and number of times to
fire the event in the <code class="highlighter-rouge">HelloObject</code>. To add a parameter, modify the
<code class="highlighter-rouge">HelloObject</code> class in the SimObject Python file
(<code class="highlighter-rouge">src/learning_gem5/HelloObject.py</code>). Parameters are set by adding new
statements to the Python class that include a <code class="highlighter-rouge">Param</code> type.</p>

<p>For instance, the following code has a parameter <code class="highlighter-rouge">time_to_wait</code> which is
a “Latency” parameter and <code class="highlighter-rouge">number_of_fires</code> which is an integer
parameter.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">HelloObject</span><span class="p">(</span><span class="n">SimObject</span><span class="p">):</span>
    <span class="nb">type</span> <span class="o">=</span> <span class="s">'HelloObject'</span>
    <span class="n">cxx_header</span> <span class="o">=</span> <span class="s">"learning_gem5/hello_object.hh"</span>

    <span class="n">time_to_wait</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">Latency</span><span class="p">(</span><span class="s">"Time before firing the event"</span><span class="p">)</span>
    <span class="n">number_of_fires</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">Int</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"Number of times to fire the event before "</span>
                                   <span class="s">"goodbye"</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="highlighter-rouge">Param.&lt;TypeName&gt;</code> declares a parameter of type <code class="highlighter-rouge">TypeName</code>. Common types
are <code class="highlighter-rouge">Int</code> for integers, <code class="highlighter-rouge">Float</code> for floats, etc. These types act like
regular Python classes.</p>

<p>Each parameter declaration takes one or two parameters. When given two
parameters (like <code class="highlighter-rouge">number_of_fires</code> above), the first parameter is the
<em>default value</em> for the parameter. In this case, if you instantiate a
<code class="highlighter-rouge">HelloObject</code> in your Python config file without specifying any value
for number_of_fires, it will take the default value of 1.</p>

<p>The second parameter to the parameter declaration is a short description
of the parameter. This must be a Python string. If you only specify a
single parameter to the parameter declaration, it is the description (as
for <code class="highlighter-rouge">time_to_wait</code>).</p>

<p>gem5 also supports many complex parameter types that are not just
builtin types. For instance, <code class="highlighter-rouge">time_to_wait</code> is a <code class="highlighter-rouge">Latency</code>. <code class="highlighter-rouge">Latency</code>
takes a value as a time value as a string and converts it into simulator
<strong>ticks</strong>. For instance, with a default tick rate of 1 picosecond
(10\^12 ticks per second or 1 THz), <code class="highlighter-rouge">"1ns"</code> is automatically converted
to 1000. There are other convenience parameters like <code class="highlighter-rouge">Percent</code>,
<code class="highlighter-rouge">Cycles</code>, <code class="highlighter-rouge">MemorySize</code> and many more.</p>

<p>Once you have declared these parameters in the SimObject file, you need
to copy their values to your C++ class in its constructor. The following
code shows the changes to the <code class="highlighter-rouge">HelloObject</code> constructor.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">HelloObject</span><span class="o">::</span><span class="n">HelloObject</span><span class="p">(</span><span class="n">HelloObjectParams</span> <span class="o">*</span><span class="n">params</span><span class="p">)</span> <span class="o">:</span>
    <span class="n">SimObject</span><span class="p">(</span><span class="n">params</span><span class="p">),</span>
    <span class="n">event</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">),</span>
    <span class="n">myName</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">),</span>
    <span class="n">latency</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">time_to_wait</span><span class="p">),</span>
    <span class="n">timesLeft</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">number_of_fires</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Created the hello object with the name %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">myName</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Here, we use the parameter’s values for the default values of latency
and timesLeft. Additionally, we store the <code class="highlighter-rouge">name</code> from the parameter
object to use it later in the member variable <code class="highlighter-rouge">myName</code>. Each <code class="highlighter-rouge">params</code>
instantiation has a name which comes from the Python config file when it
is instantiated.</p>

<p>However, assigning the name here is just an example of using the params
object. For all SimObjects, there is a <code class="highlighter-rouge">name()</code> function that always
returns the name. Thus, there is never a need to store the name like
above.</p>

<p>To the HelloObject class declaration, add a member variable for the
name.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">HelloObject</span> <span class="o">:</span> <span class="k">public</span> <span class="n">SimObject</span>
<span class="p">{</span>
  <span class="nl">private:</span>
    <span class="kt">void</span> <span class="n">processEvent</span><span class="p">();</span>

    <span class="n">EventWrapper</span><span class="o">&lt;</span><span class="n">HelloObject</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">HelloObject</span><span class="o">::</span><span class="n">processEvent</span><span class="o">&gt;</span> <span class="n">event</span><span class="p">;</span>

    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">myName</span><span class="p">;</span>

    <span class="n">Tick</span> <span class="n">latency</span><span class="p">;</span>

    <span class="kt">int</span> <span class="n">timesLeft</span><span class="p">;</span>

  <span class="nl">public:</span>
    <span class="n">HelloObject</span><span class="p">(</span><span class="n">HelloObjectParams</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span>

    <span class="kt">void</span> <span class="n">startup</span><span class="p">();</span>
<span class="p">};</span>
</code></pre></div></div>

<p>When we run gem5 with the above, we get the following error:</p>

<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 14:46:36
gem5 started Jan  4 2017 14:46:52
gem5 executing on chinook, pid 3422
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py

Global frequency set at 1000000000000 ticks per second
fatal: hello.time_to_wait without default or user set value
</code></pre></div></div>

<p>This is because the <code class="highlighter-rouge">time_to_wait</code> parameter does not have a default
value. Therefore, we need to update the Python config file
(<code class="highlighter-rouge">run_hello.py</code>) to specify this value.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">root</span><span class="o">.</span><span class="n">hello</span> <span class="o">=</span> <span class="n">HelloObject</span><span class="p">(</span><span class="n">time_to_wait</span> <span class="o">=</span> <span class="s">'2us'</span><span class="p">)</span>
</code></pre></div></div>

<p>Or, we can specify <code class="highlighter-rouge">time_to_wait</code> as a member variable. Either option is
exactly the same because the C++ objects are not created until
<code class="highlighter-rouge">m5.instantiate()</code> is called.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">root</span><span class="o">.</span><span class="n">hello</span> <span class="o">=</span> <span class="n">HelloObject</span><span class="p">()</span>
<span class="n">root</span><span class="o">.</span><span class="n">hello</span><span class="o">.</span><span class="n">time_to_wait</span> <span class="o">=</span> <span class="s">'2us'</span>
</code></pre></div></div>

<p>The output of this simple script is the following when running the the
<code class="highlighter-rouge">Hello</code> debug flag.</p>

<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 14:46:36
gem5 started Jan  4 2017 14:50:08
gem5 executing on chinook, pid 3455
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py

Global frequency set at 1000000000000 ticks per second
      0: hello: Created the hello object with the name hello
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
2000000: hello: Hello world! Processing the event! 0 left
2000000: hello: Done firing!
Exiting @ tick 18446744073709551615 because simulate() limit reached
</code></pre></div></div>

<p>You can also modify the config script to fire the event multiple times.</p>

<h2 id="other-simobjects-as-parameters">Other SimObjects as parameters</h2>

<p>You can also specify other SimObjects as parameters. To demonstrate
this, we are going to create a new SimObject, <code class="highlighter-rouge">GoodbyeObject</code>. This
object is going to have a simple function that says “Goodbye” to another
SimObject. To make it a little more interesting, the <code class="highlighter-rouge">GoodbyeObject</code> is
going to have a buffer to write the message, and a limited bandwidth to
write the message.</p>

<p>First, declare the SimObject in the SConscript file:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Import</span><span class="p">(</span><span class="s">'*'</span><span class="p">)</span>

<span class="n">SimObject</span><span class="p">(</span><span class="s">'HelloObject.py'</span><span class="p">)</span>
<span class="n">Source</span><span class="p">(</span><span class="s">'hello_object.cc'</span><span class="p">)</span>
<span class="n">Source</span><span class="p">(</span><span class="s">'goodbye_object.cc'</span><span class="p">)</span>

<span class="n">DebugFlag</span><span class="p">(</span><span class="s">'Hello'</span><span class="p">)</span>
</code></pre></div></div>

<p>The new SConscript file can be downloaded
<a href="/_pages/static/scripts/part2/parameters/SConscript">here</a>.</p>

<p>Next, you need to declare the new SimObject in a SimObject Python file.
Since the <code class="highlighter-rouge">GoodbyeObject</code> is highly related to the <code class="highlighter-rouge">HelloObject</code>, we
will use the same file. You can add the following code to
<code class="highlighter-rouge">HelloObject.py</code>.</p>

<p>This object has two parameters, both with default values. The first
parameter is the size of a buffer and is a <code class="highlighter-rouge">MemorySize</code> parameter.
Second is the <code class="highlighter-rouge">write_bandwidth</code> which specifies the speed to fill the
buffer. Once the buffer is full, the simulation will exit.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">GoodbyeObject</span><span class="p">(</span><span class="n">SimObject</span><span class="p">):</span>
    <span class="nb">type</span> <span class="o">=</span> <span class="s">'GoodbyeObject'</span>
    <span class="n">cxx_header</span> <span class="o">=</span> <span class="s">"learning_gem5/goodbye_object.hh"</span>

    <span class="n">buffer_size</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">MemorySize</span><span class="p">(</span><span class="s">'1kB'</span><span class="p">,</span>
                                   <span class="s">"Size of buffer to fill with goodbye"</span><span class="p">)</span>
    <span class="n">write_bandwidth</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">MemoryBandwidth</span><span class="p">(</span><span class="s">'100MB/s'</span><span class="p">,</span> <span class="s">"Bandwidth to fill "</span>
                                            <span class="s">"the buffer"</span><span class="p">)</span>
</code></pre></div></div>

<p>The updated <code class="highlighter-rouge">HelloObject.py</code> file can be downloaded
<a href="/_pages/static/scripts/part2/parameters/HelloObject.py">here</a>.</p>

<p>Now, we need to implement the <code class="highlighter-rouge">GoodbyeObject</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifndef __LEARNING_GEM5_GOODBYE_OBJECT_HH__
#define __LEARNING_GEM5_GOODBYE_OBJECT_HH__
</span>
<span class="cp">#include &lt;string&gt;
</span>
<span class="cp">#include "params/GoodbyeObject.hh"
#include "sim/sim_object.hh"
</span>
<span class="k">class</span> <span class="nc">GoodbyeObject</span> <span class="o">:</span> <span class="k">public</span> <span class="n">SimObject</span>
<span class="p">{</span>
  <span class="nl">private:</span>
    <span class="kt">void</span> <span class="n">processEvent</span><span class="p">();</span>

    <span class="cm">/**
     * Fills the buffer for one iteration. If the buffer isn't full, this
     * function will enqueue another event to continue filling.
     */</span>
    <span class="kt">void</span> <span class="n">fillBuffer</span><span class="p">();</span>

    <span class="n">EventWrapper</span><span class="o">&lt;</span><span class="n">GoodbyeObject</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">GoodbyeObject</span><span class="o">::</span><span class="n">processEvent</span><span class="o">&gt;</span> <span class="n">event</span><span class="p">;</span>

    <span class="c1">/// The bytes processed per tick</span>
    <span class="kt">float</span> <span class="n">bandwidth</span><span class="p">;</span>

    <span class="c1">/// The size of the buffer we are going to fill</span>
    <span class="kt">int</span> <span class="n">bufferSize</span><span class="p">;</span>

    <span class="c1">/// The buffer we are putting our message in</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span><span class="p">;</span>

    <span class="c1">/// The message to put into the buffer.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">message</span><span class="p">;</span>

    <span class="c1">/// The amount of the buffer we've used so far.</span>
    <span class="kt">int</span> <span class="n">bufferUsed</span><span class="p">;</span>

  <span class="nl">public:</span>
    <span class="n">GoodbyeObject</span><span class="p">(</span><span class="n">GoodbyeObjectParams</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span>
    <span class="o">~</span><span class="n">GoodbyeObject</span><span class="p">();</span>

    <span class="cm">/**
     * Called by an outside object. Starts off the events to fill the buffer
     * with a goodbye message.
     *
     * @param name the name of the object we are saying goodbye to.
     */</span>
    <span class="kt">void</span> <span class="n">sayGoodbye</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">);</span>
<span class="p">};</span>

<span class="cp">#endif // __LEARNING_GEM5_GOODBYE_OBJECT_HH__
</span></code></pre></div></div>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include "learning_gem5/goodbye_object.hh"
</span>
<span class="cp">#include "debug/Hello.hh"
#include "sim/sim_exit.hh"
</span>
<span class="n">GoodbyeObject</span><span class="o">::</span><span class="n">GoodbyeObject</span><span class="p">(</span><span class="n">GoodbyeObjectParams</span> <span class="o">*</span><span class="n">params</span><span class="p">)</span> <span class="o">:</span>
    <span class="n">SimObject</span><span class="p">(</span><span class="n">params</span><span class="p">),</span> <span class="n">event</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">),</span> <span class="n">bandwidth</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">write_bandwidth</span><span class="p">),</span>
    <span class="n">bufferSize</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">buffer_size</span><span class="p">),</span> <span class="n">buffer</span><span class="p">(</span><span class="nb">nullptr</span><span class="p">),</span> <span class="n">bufferUsed</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">char</span><span class="p">[</span><span class="n">bufferSize</span><span class="p">];</span>
    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Created the goodbye object</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">GoodbyeObject</span><span class="o">::~</span><span class="n">GoodbyeObject</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">buffer</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="n">GoodbyeObject</span><span class="o">::</span><span class="n">processEvent</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Processing the event!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">fillBuffer</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="n">GoodbyeObject</span><span class="o">::</span><span class="n">sayGoodbye</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">other_name</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Saying goodbye to %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">other_name</span><span class="p">);</span>

    <span class="n">message</span> <span class="o">=</span> <span class="s">"Goodbye "</span> <span class="o">+</span> <span class="n">other_name</span> <span class="o">+</span> <span class="s">"!! "</span><span class="p">;</span>

    <span class="n">fillBuffer</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="n">GoodbyeObject</span><span class="o">::</span><span class="n">fillBuffer</span><span class="p">()</span>
<span class="p">{</span>
    <span class="c1">// There better be a message</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">message</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>

    <span class="c1">// Copy from the message to the buffer per byte.</span>
    <span class="kt">int</span> <span class="n">bytes_copied</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
         <span class="n">it</span> <span class="o">&lt;</span> <span class="n">message</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">bufferUsed</span> <span class="o">&lt;</span> <span class="n">bufferSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
         <span class="n">it</span><span class="o">++</span><span class="p">,</span> <span class="n">bufferUsed</span><span class="o">++</span><span class="p">,</span> <span class="n">bytes_copied</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Copy the character into the buffer</span>
        <span class="n">buffer</span><span class="p">[</span><span class="n">bufferUsed</span><span class="p">]</span> <span class="o">=</span> <span class="o">*</span><span class="n">it</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">bufferUsed</span> <span class="o">&lt;</span> <span class="n">bufferSize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Wait for the next copy for as long as it would have taken</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Scheduling another fillBuffer in %d ticks</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
                <span class="n">bandwidth</span> <span class="o">*</span> <span class="n">bytes_copied</span><span class="p">);</span>
        <span class="n">schedule</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">curTick</span><span class="p">()</span> <span class="o">+</span> <span class="n">bandwidth</span> <span class="o">*</span> <span class="n">bytes_copied</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Goodbye done copying!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="c1">// Be sure to take into account the time for the last bytes</span>
        <span class="n">exitSimLoop</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">curTick</span><span class="p">()</span> <span class="o">+</span> <span class="n">bandwidth</span> <span class="o">*</span> <span class="n">bytes_copied</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">GoodbyeObject</span><span class="o">*</span>
<span class="n">GoodbyeObjectParams</span><span class="o">::</span><span class="n">create</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="n">GoodbyeObject</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The header file can be downloaded
<a href="/_pages/static/scripts/part2/parameters/goodbye_object.hh">here</a> and the
implementation can be downloaded
<a href="/_pages/static/scripts/part2/parameters/goodbye_object.cc">here</a>.</p>

<p>The interface to this <code class="highlighter-rouge">GoodbyeObject</code> is simple a function <code class="highlighter-rouge">sayGoodbye</code>
which takes a string as a parameter. When this function is called, the
simulator builds the message and saves it in a member variable. Then, we
begin filling the buffer.</p>

<p>To model the limited bandwidth, each time we write the message to the
buffer, we pause for the latency it takes to write the message. We use a
simple event to model this pause.</p>

<p>Since we used a <code class="highlighter-rouge">MemoryBandwidth</code> parameter in the SimObject
declaration, the <code class="highlighter-rouge">bandwidth</code> variable is automatically converted into
ticks per byte, so calculating the latency is simply the bandwidth times
the bytes we want to write the buffer.</p>

<p>Finally, when the buffer is full, we call the function <code class="highlighter-rouge">exitSimLoop</code>,
which will exit the simulation. This function takes three parameters,
the first is the message to return to the Python config script
(<code class="highlighter-rouge">exit_event.getCause()</code>), the second is the exit code, and the third is
when to exit.</p>

<h3 id="adding-the-goodbyeobject-as-a-parameter-to-the-helloobject">Adding the GoodbyeObject as a parameter to the HelloObject</h3>

<p>First, we will also add a <code class="highlighter-rouge">GoodbyeObject</code> as a parameter to the
<code class="highlighter-rouge">HelloObject</code>. To do this, you simply specify the SimObject class name
as the <code class="highlighter-rouge">TypeName</code> of the <code class="highlighter-rouge">Param</code>. You can have a default, or not, just
like a normal parameter.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">HelloObject</span><span class="p">(</span><span class="n">SimObject</span><span class="p">):</span>
    <span class="nb">type</span> <span class="o">=</span> <span class="s">'HelloObject'</span>
    <span class="n">cxx_header</span> <span class="o">=</span> <span class="s">"learning_gem5/hello_object.hh"</span>

    <span class="n">time_to_wait</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">Latency</span><span class="p">(</span><span class="s">"Time before firing the event"</span><span class="p">)</span>
    <span class="n">number_of_fires</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">Int</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"Number of times to fire the event before "</span>
                                   <span class="s">"goodbye"</span><span class="p">)</span>

    <span class="n">goodbye_object</span> <span class="o">=</span> <span class="n">Param</span><span class="o">.</span><span class="n">GoodbyeObject</span><span class="p">(</span><span class="s">"A goodbye object"</span><span class="p">)</span>
</code></pre></div></div>

<p>The updated <code class="highlighter-rouge">HelloObject.py</code> file can be downloaded
<a href="/_pages/static/scripts/part2/parameters/HelloObject.py">here</a>.</p>

<p>Second, we will add a reference to a <code class="highlighter-rouge">GoodbyeObject</code> to the
<code class="highlighter-rouge">HelloObject</code> class.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">HelloObject</span> <span class="o">:</span> <span class="k">public</span> <span class="n">SimObject</span>
<span class="p">{</span>
  <span class="nl">private:</span>
    <span class="kt">void</span> <span class="n">processEvent</span><span class="p">();</span>

    <span class="n">EventWrapper</span><span class="o">&lt;</span><span class="n">HelloObject</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">HelloObject</span><span class="o">::</span><span class="n">processEvent</span><span class="o">&gt;</span> <span class="n">event</span><span class="p">;</span>

    <span class="c1">/// Pointer to the corresponding GoodbyeObject. Set via Python</span>
    <span class="k">const</span> <span class="n">GoodbyeObject</span><span class="o">*</span> <span class="n">goodbye</span><span class="p">;</span>

    <span class="c1">/// The name of this object in the Python config file</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">myName</span><span class="p">;</span>

    <span class="c1">/// Latency between calling the event (in ticks)</span>
    <span class="k">const</span> <span class="n">Tick</span> <span class="n">latency</span><span class="p">;</span>

    <span class="c1">/// Number of times left to fire the event before goodbye</span>
    <span class="kt">int</span> <span class="n">timesLeft</span><span class="p">;</span>

  <span class="nl">public:</span>
    <span class="n">HelloObject</span><span class="p">(</span><span class="n">HelloObjectParams</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span>

    <span class="kt">void</span> <span class="n">startup</span><span class="p">();</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Then, we need to update the constructor and the process event function
of the <code class="highlighter-rouge">HelloObject</code>. We also add a check in the constructor to make
sure the <code class="highlighter-rouge">goodbye</code> pointer is valid. It is possible to pass a null
pointer as a SimObject via the parameters by using the <code class="highlighter-rouge">NULL</code> special
Python SimObject. We should <em>panic</em> when this happens since it is not a
case this object has been coded to accept.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include "learning_gem5/part2/hello_object.hh"
</span>
<span class="cp">#include "base/misc.hh"
#include "debug/Hello.hh"
</span>
<span class="n">HelloObject</span><span class="o">::</span><span class="n">HelloObject</span><span class="p">(</span><span class="n">HelloObjectParams</span> <span class="o">*</span><span class="n">params</span><span class="p">)</span> <span class="o">:</span>
    <span class="n">SimObject</span><span class="p">(</span><span class="n">params</span><span class="p">),</span>
    <span class="n">event</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">),</span>
    <span class="n">goodbye</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">goodbye_object</span><span class="p">),</span>
    <span class="n">myName</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">),</span>
    <span class="n">latency</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">time_to_wait</span><span class="p">),</span>
    <span class="n">timesLeft</span><span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">number_of_fires</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Created the hello object with the name %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">myName</span><span class="p">);</span>
    <span class="n">panic_if</span><span class="p">(</span><span class="o">!</span><span class="n">goodbye</span><span class="p">,</span> <span class="s">"HelloObject must have a non-null GoodbyeObject"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Once we have processed the number of event specified by the parameter,
we should call the <code class="highlighter-rouge">sayGoodbye</code> function in the <code class="highlighter-rouge">GoodbyeObject</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span>
<span class="n">HelloObject</span><span class="o">::</span><span class="n">processEvent</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">timesLeft</span><span class="o">--</span><span class="p">;</span>
    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Hello world! Processing the event! %d left</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">timesLeft</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">timesLeft</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">Hello</span><span class="p">,</span> <span class="s">"Done firing!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">goodbye</span><span class="p">.</span><span class="n">sayGoodbye</span><span class="p">(</span><span class="n">myName</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">schedule</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">curTick</span><span class="p">()</span> <span class="o">+</span> <span class="n">latency</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You can find the updated header file
<a href="/_pages/static/scripts/part2/parameters/hello_object.hh">here</a> and the
implementation file
<a href="/_pages/static/scripts/part2/parameters/hello_object.cc">here</a>.</p>

<h3 id="updating-the-config-script">Updating the config script</h3>

<p>Lastly, we need to add the <code class="highlighter-rouge">GoodbyeObject</code> to the config script. Create
a new config script, <code class="highlighter-rouge">hello_goodbye.py</code> and instantiate both the hello
and the goodbye objects. For instance, one possible script is the
following.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">m5</span>
<span class="kn">from</span> <span class="nn">m5.objects</span> <span class="kn">import</span> <span class="o">*</span>

<span class="n">root</span> <span class="o">=</span> <span class="n">Root</span><span class="p">(</span><span class="n">full_system</span> <span class="o">=</span> <span class="bp">False</span><span class="p">)</span>

<span class="n">root</span><span class="o">.</span><span class="n">hello</span> <span class="o">=</span> <span class="n">HelloObject</span><span class="p">(</span><span class="n">time_to_wait</span> <span class="o">=</span> <span class="s">'2us'</span><span class="p">,</span> <span class="n">number_of_fires</span> <span class="o">=</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">root</span><span class="o">.</span><span class="n">hello</span><span class="o">.</span><span class="n">goodbye_object</span> <span class="o">=</span> <span class="n">GoodbyeObject</span><span class="p">(</span><span class="n">buffer_size</span><span class="o">=</span><span class="s">'100B'</span><span class="p">)</span>

<span class="n">m5</span><span class="o">.</span><span class="n">instantiate</span><span class="p">()</span>

<span class="k">print</span> <span class="s">"Beginning simulation!"</span>
<span class="n">exit_event</span> <span class="o">=</span> <span class="n">m5</span><span class="o">.</span><span class="n">simulate</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Exiting @ tick </span><span class="si">%</span><span class="s">i because </span><span class="si">%</span><span class="s">s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">m5</span><span class="o">.</span><span class="n">curTick</span><span class="p">(),</span> <span class="n">exit_event</span><span class="o">.</span><span class="n">getCause</span><span class="p">())</span>
</code></pre></div></div>

<p>You can download this script
<a href="/_pages/static/scripts/part2/parameters/hello_goodbye.py">here</a>.</p>

<p>Running this script generates the following output.</p>

<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 15:17:14
gem5 started Jan  4 2017 15:18:41
gem5 executing on chinook, pid 3838
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/hello_goodbye.py

Global frequency set at 1000000000000 ticks per second
      0: hello.goodbye_object: Created the goodbye object
      0: hello: Created the hello object
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
2000000: hello: Hello world! Processing the event! 4 left
4000000: hello: Hello world! Processing the event! 3 left
6000000: hello: Hello world! Processing the event! 2 left
8000000: hello: Hello world! Processing the event! 1 left
10000000: hello: Hello world! Processing the event! 0 left
10000000: hello: Done firing!
10000000: hello.goodbye_object: Saying goodbye to hello
10000000: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10152592: hello.goodbye_object: Processing the event!
10152592: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10305184: hello.goodbye_object: Processing the event!
10305184: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10457776: hello.goodbye_object: Processing the event!
10457776: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10610368: hello.goodbye_object: Processing the event!
10610368: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10762960: hello.goodbye_object: Processing the event!
10762960: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10915552: hello.goodbye_object: Processing the event!
10915552: hello.goodbye_object: Goodbye done copying!
Exiting @ tick 10944163 because Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goo
</code></pre></div></div>

<p>You can modify the parameters to these two SimObjects and see how the
overall execution time (Exiting @ tick <strong>10944163</strong>) changes. To run
these tests, you may want to remove the debug flag so there is less
output to the terminal.</p>

<p>In the next chapters, we will create a more complex and more useful
SimObject, culminating with a simple blocking uniprocessor cache
implementation.</p>

  <br>

  <!-- RETRIVE PREVIOUS PAGE LINK -->
  
    
  
    
  
    
  
    
  

  <!-- RETRIEVE NEXT PAGE LINK -->
  
    
  
    
  
    
  
    
  


  <div class="navbuttons">
    
      <a href=""><button type="button" class="btn btn-outline-primary">PREVIOUS</button></a>
    

    
      <a href=""><button type="button" class="btn btn-outline-primary">NEXT</button></a>
    
  </div>
</div>

	</main>
	<footer class="page-footer">
	<div class="container">
		<div class="row">

			<div class="col-12 col-sm-4">
				<p>gem5</p>
				<p><a href="/about">About</a></p>
				<p><a href="/publications">Publications</a></p>
				<p><a href="/contributing">Contributing</a></p>
				<p><a href="/governance">Governance</a></p>
			<br></div>

			<div class="col-12 col-sm-4">
				<p>Docs</p>
				<p><a href="/documentation">Documentation</a></p>
				<p><a href="http://gem5.org/Documentation">Old Documentation</a></p>
				<p><a href="https://gem5.googlesource.com/public/gem5">Source</a></p>
			<br></div>

			<div class="col-12 col-sm-4">
				<p>Help</p>
				<p><a href="/search">Search</a></p>
				<p><a href="/mailing_lists">Mailing Lists</a></p>
				<p><a href="https://gem5.googlesource.com/public/gem5-website/+/refs/heads/master/README.md">Website Source</a></p>
			<br></div>

		</div>
	</div>
</footer>


	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
	<script src="https://unpkg.com/commentbox.io/dist/commentBox.min.js"></script>

	<script>
	  // When the user scrolls down 20px from the top of the document, show the button
	  window.onscroll = function() {scrollFunction()};

	  function scrollFunction() {
	      if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 20) {
	          document.getElementById("myBtn").style.display = "block";
	      } else {
	          document.getElementById("myBtn").style.display = "none";
	      }
	  }

	  // When the user clicks on the button, scroll to the top of the document
	  function topFunction() {
	      document.body.scrollTop = 0;
	      document.documentElement.scrollTop = 0;
	  }

		import commentBox from 'commentbox.io';
		// or
		const commentBox = require('commentbox.io');
		// or if using the CDN, it will be available as a global "commentBox" variable.

		commentBox('my-project-id');

	</script>

</body>


</html>
